home *** CD-ROM | disk | FTP | other *** search
- /*
- * Client routines for Simple Mail Transfer Protocol ala RFC821
- * A.D. Barksdale Garbee II, aka Bdale, N3EUA
- * Copyright 1986 Bdale Garbee, All Rights Reserved.
- * Permission granted for non-commercial copying and use, provided
- * this notice is retained.
- * Modified 14 June 1987 by P. Karn for symbolic target addresses,
- * also rebuilt locking mechanism
- * Copyright 1987 1988 David Trulli, All Rights Reserved.
- * Permission granted for non-commercial copying and use, provided
- * this notice is retained.
- */
- #include <stdio.h>
- #include <fcntl.h>
- #include <time.h>
- #include <setjmp.h>
- #ifdef UNIX
- #include <sys/types.h>
- #endif
- #include <dir.h>
- #include <io.h>
- #include "global.h"
- #include "mbuf.h"
- #include "cmdparse.h"
- #include "proc.h"
- #include "socket.h"
- #include "timer.h"
- #include "netuser.h"
- #include "smtp.h"
- #include "dirutil.h"
-
- extern char Badhost[];
-
- static struct timer smtpcli_t;
- static int32 gateway;
-
- #ifdef SMTPTRACE
- static int Smtptrace = 0; /* used for trace level */
- static int dosmtptrace();
- #endif
-
- static unsigned short smtpmaxcli = MAXSESSIONS; /* the max client connections allowed */
- static int smtpsessions = 0; /* number of client connections
- * currently open */
- int Smtpmode = 0;
-
- static struct smtpcli *cli_session[MAXSESSIONS]; /* queue of client sessions */
-
- static char quitcmd[] = "QUIT\r\n";
- static char eom[] = "\r\n.\r\n";
-
- static void abort_trans __ARGS((struct smtpcli *cb));
- static void del_job __ARGS((struct smtp_job *jp));
- static void del_session __ARGS((struct smtpcli *cb));
- static int dogateway __ARGS((int argc,char *argv[],void *p));
- static int dosmtpmaxcli __ARGS((int argc,char *argv[],void *p));
- static int dotimer __ARGS((int argc,char *argv[],void *p));
- static void execjobs __ARGS((void));
- static void logerr __ARGS((struct smtpcli *cb));
- static struct smtpcli *lookup __ARGS((int32 destaddr));
- static struct smtpcli *newcb __ARGS((void));
- static int next_job __ARGS((struct smtpcli *cb));
- static void retmail __ARGS((struct smtpcli *cb));
- static void sendcmd __ARGS((struct smtpcli *cb,char *fmt,...));
- static int sendfile __ARGS((struct smtpcli *cb));
- static void sendquit __ARGS((struct smtpcli *cb));
- static int setsmtpmode __ARGS((int argc,char *argv[],void *p));
- static struct smtp_job *setupjob __ARGS((struct smtpcli *cb,char *id,char *from));
- static void smtp_send __ARGS((int unused,void *cb1,void *p));
- static int smtpkick __ARGS((int argc,char *argv[],void *p));
-
- static struct cmds Smtpcmds[] = {
- "gateway", dogateway, 0, 0, NULLCHAR,
- "mode", setsmtpmode, 0, 0, NULLCHAR,
- "kick", smtpkick, 0, 0, NULLCHAR,
- "maxclients", dosmtpmaxcli, 0, 0, NULLCHAR,
- "timer", dotimer, 0, 0, NULLCHAR,
- #ifdef SMTPTRACE
- "trace", dosmtptrace, 0, 0, NULLCHAR,
- #endif
- NULLCHAR,
- };
-
- int
- dosmtp(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- return subcmd(Smtpcmds,argc,argv,p);
- }
-
- static int
- dosmtpmaxcli(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- return setshort(&smtpmaxcli,"Max clients",argc,argv);
- }
-
- static int
- setsmtpmode(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- if (argc < 2) {
- printf("smtp mode: %s\n",
- (Smtpmode & QUEUE) ? "queue" : "route");
- } else {
- switch(*argv[1]) {
- case 'q':
- Smtpmode |= QUEUE;
- break;
- case 'r':
- Smtpmode &= ~QUEUE;
- break;
- default:
- printf("Usage: smtp mode [queue | route]\n");
- break;
- }
- }
- return 0;
- }
- static int
- dogateway(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- int32 n;
-
- if(argc < 2){
- printf("%s\n",inet_ntoa(gateway));
- } else if((n = resolve(argv[1])) == 0){
- printf(Badhost,argv[1]);
- return 1;
- } else
- gateway = n;
- return 0;
- }
-
- #ifdef SMTPTRACE
- static int
- dosmtptrace(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- return setbool(&Smtptrace,"SMTP tracing",argc,argv);
- }
- #endif
-
- /* Set outbound spool scan interval */
- static int
- dotimer(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- if(argc < 2){
- printf("%lu/%lu\n",
- (smtpcli_t.start - smtpcli_t.count)/(1000/MSPTICK),
- smtpcli_t.start/(1000/MSPTICK));
- return 0;
- }
- smtpcli_t.func = (void (*)())smtptick;/* what to call on timeout */
- smtpcli_t.arg = NULL; /* dummy value */
- smtpcli_t.start = atol(argv[1])*(1000/MSPTICK); /* set timer duration */
- start_timer(&smtpcli_t); /* and fire it up */
- return 0;
- }
-
- static int
- smtpkick(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- smtptick(NULL);
- return 0;
- }
-
- /* This is the routine that gets called every so often to do outgoing
- * mail processing. When called with a null argument, it runs the entire
- * queue; if called with a specific non-zero IP address from the remote
- * kick server, it only starts up sessions to that address.
- */
- int
- smtptick(t)
- void *t;
- {
- register struct smtpcli *cb;
- struct smtp_job *jp;
- struct list *ap;
- char tmpstring[LINELEN], wfilename[13], prefix[9];
- char from[LINELEN], to[LINELEN];
- char *cp, *cp1;
- int32 destaddr,target;
- FILE *wfile;
-
- target = (int32)t;
- #ifdef SMTPTRACE
- if (Smtptrace > 5)
- printf("smtp daemon entered, target = %s\n",inet_ntoa(target));
- #endif
- for(filedir(Mailqueue,0,wfilename);wfilename[0] != '\0';
- filedir(Mailqueue,1,wfilename)){
-
- /* save the prefix of the file name which it job id */
- cp = wfilename;
- cp1 = prefix;
- while (*cp && *cp != '.')
- *cp1++ = *cp++;
- *cp1 = '\0';
-
- /* lock this file from the smtp daemon */
- if (mlock(Mailqdir,prefix))
- continue;
-
- sprintf(tmpstring,"%s/%s",Mailqdir,wfilename);
- if ((wfile = fopen(tmpstring,READ_TEXT)) == NULLFILE) {
- /* probably too many open files */
- (void) rmlock(Mailqdir,prefix);
- /* continue to next message. The failure
- * may be temporary */
- continue;
- }
-
- (void) fgets(tmpstring,LINELEN,wfile); /* read target host */
- rip(tmpstring);
-
- if ((destaddr = mailroute(tmpstring)) == 0) {
- fclose(wfile);
- printf("** smtp: Unknown address %s\n",tmpstring);
- (void) rmlock(Mailqdir,prefix);
- continue;
- }
- if(target != 0 && destaddr != target){
- fclose(wfile);
- (void) rmlock(Mailqdir,prefix);
- continue; /* Not the proper target of a kick */
- }
- if ((cb = lookup(destaddr)) == NULLSMTPCLI) {
- /* there are enough processes running already */
- if (smtpsessions >= smtpmaxcli) {
- #ifdef SMTPTRACE
- if (Smtptrace) {
- printf("smtp daemon: too many processes\n");
- }
- #endif
- fclose(wfile);
- (void) rmlock(Mailqdir,prefix);
- break;
- }
- if ((cb = newcb()) == NULLSMTPCLI) {
- fclose(wfile);
- (void) rmlock(Mailqdir,prefix);
- break;
- }
- cb->ipdest = destaddr;
- } else {
- /* This system is already is sending mail lets not
- * interfere with its send queue.
- */
- if (cb->state != CLI_INIT_STATE) {
- fclose(wfile);
- (void) rmlock(Mailqdir,prefix);
- continue;
- }
- }
-
- (void) fgets(from,LINELEN,wfile); /* read from */
- rip(from);
- if ((jp = setupjob(cb,prefix,from)) == NULLJOB) {
- fclose(wfile);
- (void) rmlock(Mailqdir,prefix);
- del_session(cb);
- break;
- }
- while (fgets(to,LINELEN,wfile) != NULLCHAR) {
- rip(to);
- if (addlist(&jp->to,to,DOMAIN) == NULLLIST) {
- fclose(wfile);
- del_session(cb);
- }
- }
- fclose(wfile);
- #ifdef SMTPTRACE
- if (Smtptrace > 1) {
- printf("queue job %s From: %s To:",prefix,from);
- for (ap = jp->to; ap != NULLLIST; ap = ap->next)
- printf(" %s",ap->val);
- printf("\n");
- }
- #endif
- }
-
- /* start sending that mail */
- execjobs();
-
- /* Restart timer */
- start_timer(&smtpcli_t);
- return 0;
- }
-
- /* this is the master state machine that handles a single SMTP transaction */
- /* it is called with a queue of jobs for a particular host. */
- static void
- smtp_send(unused,cb1,p)
- int unused;
- void *cb1;
- void *p;
- {
- register struct smtpcli *cb;
- register char reply;
- register struct list *tp;
- struct sockaddr_in fsocket;
- struct mbuf *bp,*bpl;
- char *cp;
- char tbuf[LINELEN];
- int rcode;
-
- cb = (struct smtpcli *)cb1;
- fsocket.sin_family = AF_INET;
- fsocket.sin_addr.s_addr = cb->ipdest;
- fsocket.sin_port = IPPORT_SMTP;
-
- cb->s = socket(AF_INET,SOCK_STREAM,0);
- cb->state = CLI_OPEN_STATE; /* init state placeholder */
- #ifdef SMTPTRACE
- if (Smtptrace)
- printf("SMTP client Trying...\n");
- #endif
- if(connect(cb->s,(char *)&fsocket,SOCKSIZE) == 0){
- #ifdef SMTPTRACE
- if (Smtptrace)
- printf("Connected\n");
- #endif
- ;
- } else {
- cp = sockerr(cb->s);
- #ifdef SMTPTRACE
- if (Smtptrace)
- printf("Connect failed: %s\n",cp != NULLCHAR ? cp : "");
- #endif
- log(cb->s,"Connect failed: %s\n",cp != NULLCHAR ? cp : "");
- }
-
- while(1) {
-
- if (recvline(cb->s,cb->buf,LINELEN) == -1)
- goto quit;
- rip(cb->buf);
- #ifdef SMTPTRACE
- if (Smtptrace)
- printf("smtp rcvd: '%s'\n",cb->buf);
- #endif
-
- /* Another line follows, ignore this one */
- if(cb->buf[0] == '0' || cb->buf[3] == '-')
- continue;
-
- reply = cb->buf[0];
- rcode = atoi(cb->buf);
-
- /* if service shuting down */
- if (rcode == 421) {
- sendquit(cb);
- continue;
- }
-
- switch(cb->state) {
- case CLI_OPEN_STATE:
- if (reply != '2')
- sendquit(cb);
- else {
- cb->state = CLI_HELO_STATE;
- sendcmd(cb,"HELO %s\r\nMAIL FROM:<%s>\r\n",
- Hostname,cb->jobq->from);
- }
- break;
- case CLI_HELO_STATE:
- if (reply != '2')
- sendquit(cb);
- else
- cb->state = CLI_MAIL_STATE;
- break;
- case CLI_MAIL_STATE:
- if (reply != '2')
- sendquit(cb);
- else {
- cb->state = CLI_RCPT_STATE;
- cb->rcpts = 0;
- bpl = NULLBUF;
- for (tp = cb->jobq->to; tp != NULLLIST; tp = tp->next){
- sprintf(tbuf,"RCPT TO:<%s>\r\n",tp->val);
- bp = qdata(tbuf,(int16)strlen(tbuf));
- if (bp == NULLBUF) {
- free_p(bpl);
- sendquit(cb);
- goto quit;
- }
- append(&bpl,bp);
- cb->rcpts++;
- #ifdef SMTPTRACE
- if (Smtptrace) {
- printf("smtp sent: %s",tbuf);
- }
- #endif
- }
- send_mbuf(cb->s,bpl,0,NULLCHAR,0);
- }
- break;
- case CLI_RCPT_STATE:
- if (reply == '5') {
- logerr(cb);
- } else if (reply == '2') {
- cb->goodrcpt = 1;
- } else {
- /* some kind of temporary failure */
- abort_trans(cb);
- break;
- }
- /* if more rcpts stay in this state */
- if (--cb->rcpts != 0)
- break;
-
- /* check for no good rcpt on the list */
- if (cb->goodrcpt == 0) {
- if (cb->errlog != NULLLIST)
- retmail(cb);
- (void) unlink(cb->wname); /* unlink workfile */
- (void) unlink(cb->tname); /* unlink text */
- abort_trans(cb);
- break;
- }
- /* if this file open fails abort */
- if ((cb->tfile = fopen(cb->tname,READ_TEXT)) == NULLFILE)
- abort_trans(cb);
- else {
- sendcmd(cb,"DATA\r\n");
- cb->state = CLI_SEND_STATE;
- }
- break;
- case CLI_SEND_STATE:
- if (reply == '3') {
- cb->state = CLI_UNLK_STATE;
- sendfile(cb);
- } else {
- sendquit(cb);
- }
- break;
- case CLI_UNLK_STATE:
- /* if a good transfer or permanent failure remove job */
- if (reply == '2' || reply == '5') {
- if (reply == '5')
- logerr(cb);
- /* close and unlink the textfile */
- if(cb->tfile != NULLFILE) {
- fclose(cb->tfile);
- cb->tfile = NULLFILE;
- }
- if (cb->errlog != NULLLIST)
- retmail(cb);
- (void) unlink(cb->tname);
- (void) unlink(cb->wname); /* unlink workfile */
- log(cb->s,"SMTP sent job %s To: %s From: %s",
- cb->jobq->jobname,cb->jobq->to->val,cb->jobq->from);
- }
- if (next_job(cb)) {
- cb->state = CLI_MAIL_STATE;
- sendcmd(cb,"MAIL FROM:<%s>\r\n",cb->jobq->from);
- } else {
- sendquit(cb);
- cb->state = CLI_QUIT_STATE;
- }
- break;
- case CLI_IDLE_STATE: /* used after a RSET and more mail to send */
- if (reply != '2')
- sendquit(cb);
- else {
- cb->state = CLI_MAIL_STATE;
- sendcmd(cb,"MAIL FROM:<%s>\r\n",cb->jobq->from);
- }
- break;
- case CLI_QUIT_STATE:
- goto quit;
- }
- }
- quit:
- (void) close_s(cb->s);
- if(cb->tfile != NULLFILE)
- fclose(cb->tfile);
- del_session(cb);
- }
-
- /* abort the currrent job.
- * If more work exists set up the next job if
- * not then shut down.
- */
- static void
- abort_trans(cb)
- register struct smtpcli *cb;
- {
- #ifdef SMTPSTRACE
- if (Smtptrace)
- printf("smtpcli: abort transaction\n");
- #endif
- if(cb->tfile != NULLFILE) {
- fclose(cb->tfile);
- cb->tfile = NULLFILE;
- }
- if (next_job(cb)) {
- sendcmd(cb,"RSET\r\n");
- cb->state = CLI_IDLE_STATE;
- } else
- sendquit(cb);
- }
-
- void
- static sendquit(cb)
- struct smtpcli *cb;
- {
- cb->state = CLI_QUIT_STATE;
- sendcmd(cb,quitcmd); /* issue a quit command */
- }
-
- /* Send message back to server */
- #ifdef ANSIPROTO
- static void
- sendcmd(struct smtpcli *cb,char *fmt,...)
- {
- va_list ap;
- struct mbuf *bp;
- char tmpstring[256];
-
- va_start(ap,fmt);
-
- #ifdef SMTPTRACE
- if (Smtptrace) {
- printf("smtp sent: ");
- vprintf(fmt,ap);
- }
- #endif
- vsprintf(tmpstring,fmt,ap);
- va_end(ap);
- bp = qdata(tmpstring,(int16)strlen(tmpstring));
- send_mbuf(cb->s,bp,0,NULLCHAR,0);
- }
- #else
- static void
- sendcmd(cb,fmt,arg1,arg2)
- struct smtpcli *cb;
- char *fmt,*arg1,*arg2;
- {
- struct mbuf *bp;
- char tmpstring[256];
-
- #ifdef SMTPTRACE
- if (Smtptrace) {
- printf("smtp sent: ");
- printf(fmt,arg1,arg2);
- }
- #endif
- sprintf(tmpstring,fmt,arg1,arg2);
- bp = qdata(tmpstring,(int16)strlen(tmpstring));
- send_mbuf(cb->s,bp,0,NULLCHAR,0);
- }
- #endif
- /* create mail lockfile */
- int
- mlock(dir,id)
- char *dir,*id;
- {
- char lockname[LINELEN];
- int fd;
-
- /* Try to create the lock file in an atomic operation */
- sprintf(lockname,"%s/%s.lck",dir,id);
- if((fd = open(lockname, O_WRONLY|O_EXCL|O_CREAT,0600)) == -1)
- return -1;
- close(fd);
- return 0;
- }
-
- /* remove mail lockfile */
- int
- rmlock(dir,id)
- char *dir,*id;
- {
- char lockname[LINELEN];
- sprintf(lockname,"%s/%s.lck",dir,id);
- return(unlink(lockname));
- }
-
- /* free the message struct and data */
- static void
- del_session(cb)
- register struct smtpcli *cb;
- {
- register struct smtp_job *jp,*tp;
- register int i;
-
- if (cb == NULLSMTPCLI)
- return;
- for(i=0; i<MAXSESSIONS; i++)
- if(cli_session[i] == cb) {
- cli_session[i] = NULLSMTPCLI;
- break;
- }
-
- free(cb->wname);
- free(cb->tname);
- for (jp = cb->jobq; jp != NULLJOB;jp = tp) {
- tp = jp->next;
- del_job(jp);
- }
- del_list(cb->errlog);
- free((char *)cb);
- smtpsessions--; /* number of connections active */
- }
-
- static void
- del_job(jp)
- register struct smtp_job *jp;
- {
- if ( *jp->jobname != '\0')
- (void) rmlock(Mailqdir,jp->jobname);
- free(jp->from);
- del_list(jp->to);
- free((char *)jp);
- }
-
- /* delete a list of list structs */
- void
- del_list(lp)
- struct list *lp;
- {
- register struct list *tp, *tp1;
- for (tp = lp; tp != NULLLIST; tp = tp1) {
- tp1 = tp->next;
- free(tp->val);
- free((char *)tp);
- }
- }
-
- /* return message to sender */
- static void
- retmail(cb)
- struct smtpcli *cb;
- {
- register struct list *lp;
- register FILE *tfile;
- register int c;
- FILE *infile;
- char *to;
- time_t t;
-
- #ifdef SMTPTRACE
- if (Smtptrace > 5) {
- printf("smtp job %s returned to sender\n",cb->wname);
- }
- #endif
- /* A null From<> so no looping replys to MAIL-DAEMONS */
- to = cb->jobq->from;
- if (*to == '\0')
- return;
- if ((infile = fopen(cb->tname,READ_TEXT)) == NULLFILE)
- return;
- if ((tfile = tmpfile()) == NULLFILE) {
- fclose(infile);
- return;
- }
- time(&t);
- fprintf(tfile,"Date: %s",ptime(&t));
- fprintf(tfile,"Message-Id: <%ld@%s>\n",get_msgid(),Hostname);
- fprintf(tfile,"From: MAILER-DAEMON@%s\n",Hostname);
- fprintf(tfile,"To: %s\n",to);
- fprintf(tfile,"Subject: Failed mail\n\n");
- fprintf(tfile," ===== transcript follows =====\n\n");
-
- for (lp = cb->errlog; lp != NULLLIST; lp = lp->next)
- fprintf(tfile,"%s\n",lp->val);
-
- fprintf(tfile,"\n ===== Unsent message follows ====\n");
-
- while((c = getc(infile)) != EOF)
- if (putc(c,tfile) == EOF)
- break;
- fclose(infile);
- fseek(tfile,0L,0);
- (void) mailuser(tfile,"",to);
- fclose(tfile);
- }
-
- /* look to see if a smtp control block exists for this ipdest */
- static struct smtpcli *
- lookup(destaddr)
- int32 destaddr;
- {
- register int i;
-
- for(i=0; i<MAXSESSIONS; i++) {
- if (cli_session[i] == NULLSMTPCLI)
- continue;
- if(cli_session[i]->ipdest == destaddr)
- return cli_session[i];
- }
- return NULLSMTPCLI;
- }
-
- /* create a new smtp control block */
- static struct smtpcli *
- newcb()
- {
- register int i;
- register struct smtpcli *cb;
-
- for(i=0; i<MAXSESSIONS; i++) {
- if(cli_session[i] == NULLSMTPCLI) {
- cb = (struct smtpcli *)calloc(1,sizeof(struct smtpcli));
- if (cb == NULLSMTPCLI)
- return(NULLSMTPCLI);
- cb->wname = malloc((unsigned)strlen(Mailqdir)+JOBNAME);
- if (cb->wname == NULLCHAR) {
- free((char *)cb);
- return(NULLSMTPCLI);
- }
- cb->tname = malloc((unsigned)strlen(Mailqdir)+JOBNAME);
- if (cb->tname == NULLCHAR) {
- free(cb->wname);
- free((char *)cb);
- return(NULLSMTPCLI);
- }
- cb->state = CLI_INIT_STATE;
- cli_session[i] = cb;
- smtpsessions++; /* number of connections active */
- return(cb);
- }
- }
- return NULLSMTPCLI;
- }
-
- static void
- execjobs()
- {
- register struct smtpcli *cb;
- register int i;
-
- for(i=0; i<MAXSESSIONS; i++) {
- cb = cli_session[i];
- if (cb == NULLSMTPCLI)
- continue;
- if(cb->state != CLI_INIT_STATE)
- continue;
-
- sprintf(cb->tname,"%s/%s.txt",Mailqdir,cb->jobq->jobname);
- sprintf(cb->wname,"%s/%s.wrk",Mailqdir,cb->jobq->jobname);
-
- newproc("smtp_send", 1024, smtp_send, 0, cb,NULL);
-
- #ifdef SMTPTRACE
- if (Smtptrace)
- printf("Trying Connection to %s\n",inet_ntoa(cb->ipdest));
- #endif
-
-
- }
- }
-
- /* add this job to control block queue */
- static struct smtp_job *
- setupjob(cb,id,from)
- struct smtpcli *cb;
- char *id,*from;
- {
- register struct smtp_job *p1,*p2;
-
- p1 = (struct smtp_job *)calloc(1,sizeof(struct smtp_job));
- if (p1 == NULLJOB)
- return NULLJOB;
- p1->from = malloc((unsigned)strlen(from) + 1);
- if (p1->from == NULLCHAR) {
- free((char *)p1);
- return NULLJOB;
- }
- strcpy(p1->from,from);
- strcpy(p1->jobname,id);
- /* now add to end of jobq */
- if ((p2 = cb->jobq) == NULLJOB)
- cb->jobq = p1;
- else {
- while(p2->next != NULLJOB)
- p2 = p2->next;
- p2->next = p1;
- }
- return p1;
- }
-
- /* called to advance to the next job */
- static int
- next_job(cb)
- register struct smtpcli *cb;
- {
- register struct smtp_job *jp;
-
- jp = cb->jobq->next;
- del_job(cb->jobq);
- if (jp == NULLJOB) {
- cb->jobq = NULLJOB;
- return 0;
- }
- /* remove the error log of previous message */
- del_list(cb->errlog);
- cb->errlog = NULLLIST;
- cb->goodrcpt = 0;
- cb->jobq = jp;
- sprintf(cb->tname,"%s/%s.txt",Mailqdir,jp->jobname);
- sprintf(cb->wname,"%s/%s.wrk",Mailqdir,jp->jobname);
- #ifdef SMTPTRACE
- if (Smtptrace > 5) {
- printf("sending job %s\n",jp->jobname);
- }
- #endif
- return 1;
-
- }
-
-
- /* mail routing funtion. For now just used the hosts file */
- int32
- mailroute(dest)
- char *dest;
- {
- int32 destaddr;
-
- /* look up address or use the gateway */
- if ((destaddr = resolve(dest)) == 0)
- if (gateway != 0)
- destaddr = gateway; /* Use the gateway */
- return destaddr;
-
- }
-
- /* save error reply for in error list */
- static void
- logerr(cb)
- struct smtpcli *cb;
- {
- register struct list *lp,*tp;
- if ((tp = (struct list *)calloc(1,sizeof(struct list))) == NULLLIST)
- return;
- if ((tp->val = malloc((unsigned)strlen(cb->buf)+1)) == NULLCHAR) {
- free((char *)tp);
- return;
- }
- /* find end of list */
- if ((lp = cb->errlog) == NULLLIST)
- cb->errlog = tp;
- else {
- while(lp->next != NULLLIST)
- lp = lp->next;
- lp->next = tp;
- }
- strcpy(tp->val,cb->buf);
- }
-
- static int
- sendfile(cb)
- register struct smtpcli *cb;
- {
- register int c;
- char *cp;
- register struct mbuf *bp;
- int sawnl = 1;
- int error = 0;
-
- for(;;) {
- /* Hard to know what to do here */
- if ((bp = alloc_mbuf(BUFSIZ)) == NULLBUF)
- return EOF;
- cp = bp->data;
- while(bp->cnt < BUFSIZ-2 && (c = fgetc(cb->tfile)) != EOF){
- if (c == '\r') /* strip cr from some pc hosts */
- continue;
- if (c == '\n') { /* send line end as \r\n */
- *cp++ = '\r';
- bp->cnt++;
- sawnl = 1;
- } else {
- /* special case of a line with just a . sent as .. one it */
- if (c == '.' && sawnl) {
- c = fgetc(cb->tfile);
- if ( c != EOF && c != '\n' && c != '\r')
- ungetc(c,cb->tfile);
- else {
- *cp++ = '.';
- bp->cnt++;
- }
- c = '.';
- }
- sawnl = 0;
- }
- *cp++ = c;
- bp->cnt++;
- }
- if(bp->cnt != 0) {
- if(send_mbuf(cb->s,bp,0,NULLCHAR,0) == -1){
- error = 1;
- break;
- }
- } else {
- free_p(bp);
- break;
- }
- }
- fclose(cb->tfile);
- cb->tfile = NULLFILE;
- sendcmd(cb,eom);
- return error;
- }
-